import uuid from "./uuid";

export const MBProtocalType = {
    //------------------------------------------------- from client
    /* 由客户端发出 - 协议类型：客户端登陆 */
    FROM_CLIENT_TYPE_OF_LOGIN: 0,
    /* 由客户端发出 - 协议类型：心跳包 */
    FROM_CLIENT_TYPE_OF_KEEP$ALIVE: 1,
    /* 由客户端发出 - 协议类型：发送通用数据 */
    FROM_CLIENT_TYPE_OF_COMMON$DATA: 2,
    /* 由客户端发出 - 协议类型：客户端退出登陆 */
    FROM_CLIENT_TYPE_OF_LOGOUT: 3,
    /* 由客户端发出 - 协议类型：QoS保证机制中的消息应答包（目前只支持客户端间的QoS机制哦） */
    FROM_CLIENT_TYPE_OF_RECIVED: 4,
    /* 由客户端发出 - 协议类型：C2S时的回显指令（此指令目前仅用于测试时） */
    FROM_CLIENT_TYPE_OF_ECHO: 5,

    //------------------------------------------------- from server
    /* 由服务端发出 - 协议类型：响应客户端的登陆 */
    FROM_SERVER_TYPE_OF_RESPONSE$LOGIN: 50,
    /* 由服务端发出 - 协议类型：响应客户端的心跳包 */
    FROM_SERVER_TYPE_OF_RESPONSE$KEEP$ALIVE: 51,
    /* 由服务端发出 - 协议类型：反馈给客户端的错误信息 */
    FROM_SERVER_TYPE_OF_RESPONSE$FOR$ERROR: 52,
    /* 由服务端发出 - 协议类型：反馈回显指令给客户端 */
    FROM_SERVER_TYPE_OF_RESPONSE$ECHO: 53,
    /* 由服务端发出 - 协议类型：向客户端发出“重复登陆被踢”指令 */
    FROM_SERVER_TYPE_OF_KICKOUT: 54

    
};



/**
 * 错误码常量表.<br>
 * <b>建议0~1024范围内的错误码作为MobileIMSDK核心框架保留，业务层请使用>1024的码表示！</b>
 */
export const MBErrorCode = {

    /* 一切正常 */
    COMMON_CODE_OK: 0,
    /* 客户端尚未登陆 */
    COMMON_NO_LOGIN: 1,
    /* 未知错误 */
    COMMON_UNKNOW_ERROR: 2,
    /* 数据发送失败 */
    COMMON_DATA_SEND_FAILD: 3,
    /* 无效的 {@link Protocal}对象 */
    COMMON_INVALID_PROTOCAL: 4,

    //------------------------------------------------- 由客户端产生的错误码
    /* 与服务端的连接已断开 */
    BREOKEN_CONNECT_TO_SERVER: 201,
    /* 与服务端的网络连接失败 */
    BAD_CONNECT_TO_SERVER: 202,
    /* 客户端SDK尚未初始化 */
    CLIENT_SDK_NO_INITIALED: 203,
    /* 本地网络不可用（未打开） */
    LOCAL_NETWORK_NOT_WORKING: 204,
    /* 要连接的服务端网络参数未设置 */
    TO_SERVER_NET_INFO_NOT_SETUP: 205,

    //------------------------------------------------- 由服务端产生的错误码
    /* 客户端尚未登陆，请重新登陆 */
    RESPONSE_FOR_UNLOGIN: 301
};

/**
 * Socket事件名定义。
 *
 * MobileIMSDK H5版客户端框架中，各种网络事件是通过事件通知的方法抛出，从而与主逻辑解耦，
 * 机制上与Andriod端的机制EventBus类似，与socket.io中的实现思路是一致的。
 */
export const MBSocketEvent = {

    SOCKET_EVENT_ON_LOGIN_RESPONSE: "onLoginResponse",
    SOCKET_EVENT_ON_LINK_CLOSE: "onLinkClose",

    SOCKET_EVENT_ON_RECIEVE_MESSAGE: "onRecieveMessage",
    SOCKET_EVENT_ON_ERROR_RESPONSE: "onErrorResponse",

    SOCKET_EVENT_MESSAGE_LOST: "messagesLost",
    SOCKET_EVENT_MESSAGE_BE_RECIEVED: "messagesBeReceived",

    SOCKET_EVENT_RECONNECT_ATTEMPT: "reconnect_attempt",

    /* 网络事件：心跳包（客户端发出的） */
    SOCKET_EVENT_PING: "ping",
    /* 网络事件：心跳包（客户端收到的） */
    SOCKET_EVENT_PONG: "pong",

    /* 网络事件：客户端已被强行踢出 */
    SOCKET_EVENT_KICKOUT: "kickout"
};

/**
 * 被踢原因编码常量。
 */
export const MBKickoutCode = {
    /* 被踢原因编码：因重复登陆被踢 */
    KICKOUT_FOR_DUPLICATE_LOGIN: 1,
    /* 被踢原因编码：被管理员强行踢出 */
    KICKOUT_FOR_ADMIN: 2
};

/**
 * MobileIMSDK核心框架预设的敏感度模式.
 *
 * <p>
 * 对于客户端而言，此模式决定了用户与服务端网络会话的健康模式，原则上超敏感客户端的体验越好。
 *
 * <p>
 * <b>重要说明：</b><u>客户端本模式的设定必须要与服务端的模式设制保持一致</u>，否则可能因参数的不一致而导致
 * IM算法的不匹配，进而出现不可预知的问题。
 *
 * @author Jack Jiang
 */
export const MBSenseMode = {

    /*
     * 此模式下：<br>
     * - KeepAlive心跳问隔为3秒；<br>
     * - 5秒后未收到服务端心跳反馈即认为连接已断开（相当于连续1个心跳间隔+2秒链路延迟容忍时间后仍未收到服务端反馈）。
     */
    MODE_3S: 1,

    /*
     * 此模式下：<br>
     * - KeepAlive心跳问隔为5秒；<br>
     * - 8秒后未收到服务端心跳反馈即认为连接已断开（相当于连续1个心跳间隔+3秒链路延迟容忍时间后仍未收到服务端反馈）。
     */
    MODE_5S: 2,

    /*
     * 此模式下：<br>
     * - KeepAlive心跳问隔为10秒；<br>
     * - 15秒后未收到服务端心跳反馈即认为连接已断开（相当于连续1个心跳间隔+5秒链路延迟容忍时间后仍未收到服务端反馈）。
     */
    MODE_10S: 3,

    /*
     * 此模式下：<br>
     * - KeepAlive心跳问隔为15秒；<br>
     * - 20秒后未收到服务端心跳反馈即认为连接已断开（相当于连续1个心跳间隔+5秒链路延迟容忍时间后仍未收到服务端反馈）。
     */
    MODE_15S: 4,

    /*
     * 此模式下：<br>
     * - KeepAlive心跳问隔为30秒；<br>
     * - 35秒后未收到服务端心跳反馈即认为连接已断开（相当于连续1个心跳间隔+5秒链路延迟容忍时间后仍未收到服务端反馈）。
     */
    MODE_30S: 5,

    /*
     * 此模式下：<br>
     * - KeepAlive心跳问隔为60秒；<br>
     * - 65秒后未收到服务端心跳反馈即认为连接已断开（相当于连续1个心跳间隔+5秒链路延迟容忍时间后仍未收到服务端反馈）。
     */
    MODE_60S: 6,

    /*
     * 此模式下：<br>
     * - KeepAlive心跳问隔为120秒；<br>
     * - 125秒后未收到服务端心跳反馈即认为连接已断开（相当于连续1个心跳间隔+5秒链路延迟容忍时间后仍未收到服务端反馈）。
     */
    MODE_120S: 7
};


export class Protocal {
    type?: number;
    dataContent: any;
    from: string | null;
    to: string;
    fp: string | null;
    QoS: boolean;
    typeu: number;
    retryCount?: number;

    constructor() {
        this.type = 0;
        this.dataContent = null;
        this.from = "-1";
        this.to = "-1";
        this.fp = null;
        this.QoS = false;
        this.typeu = -1;
        this.retryCount = 0;
    }
}


class MBProtocalFactory {

    createProtocal({ type, dataContent, from, to, QoS, fp, typeu }: Protocal) {
        var p = new Protocal();
        p.type = type;
        p.dataContent = dataContent;
        p.from = from;
        p.to = to;
        p.typeu = typeu;
        p.QoS = QoS;
        // 只有在需要QoS支持时才生成指纹，否则浪费数据传输流量
        // 目前一个包的指纹只在对象建立时创建哦
        if (QoS) {
            p.fp = (fp ? fp : uuid.v1());
        }
        return p;
    }

    createCommonData({ dataContent, from, to, QoS, fp, typeu }: Protocal) {
        const type = MBProtocalType.FROM_CLIENT_TYPE_OF_COMMON$DATA;
        return this.createProtocal({
            type, dataContent
            , from, to, QoS, fp, typeu
        });
    }

    createCommonDataSimple({ dataContent, from, to, typeu }: any) {
        return this.createCommonData({ dataContent, from, to, QoS: true, fp: null, typeu });
    };


    createPKeepAlive({ from }: any) {
        const type = MBProtocalType.FROM_CLIENT_TYPE_OF_KEEP$ALIVE;
        return this.createProtocal({
            type
            , dataContent: "{}", from, to: "0", QoS: false, fp: null, typeu: -1
        });
    };


    createPLoginoutInfo({ from }: any) {
        const type = MBProtocalType.FROM_CLIENT_TYPE_OF_LOGOUT;
        return this.createProtocal({ type, dataContent: null, from, to: '0', QoS: false, fp: null, typeu: -1 });
    };

    createPLoginInfo({ userId, loginInfo }: any) {

        // var loginInfo = {
        //     loginUserId : userId,
        //     loginToken  : token,
        //     extra       : extra
        // };

        // 因登陆额外处理丢包逻辑，所以此包也无需QoS支持。不能支持QoS的原因
        // 是：登陆时QoS机制都还没启用呢（只在登陆成功后启用），所以此处无需设置且设置了也没有用的哦

        const type = MBProtocalType.FROM_CLIENT_TYPE_OF_LOGIN;
        return this.createProtocal({ type, dataContent: JSON.stringify(loginInfo), from: userId, to: '0', QoS: false, fp: null, typeu: -1 });
    };

    createRecivedBack(from: any, to: any, recievedMessageFingerPrint: any) {
        const type = MBProtocalType.FROM_CLIENT_TYPE_OF_RECIVED;
        return this.createProtocal({ type, dataContent: recievedMessageFingerPrint, from, to, QoS: false, fp: null, typeu: - 1 });
    };
}

export default new MBProtocalFactory();
